package org.flow.basic.threadpool;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
 * @author xl-9527
 * @since 2024/10/28
 **/
public class CompletableFutureRuntimeDemo {

    private final Logger log = LoggerFactory.getLogger(CompletableFutureRuntimeDemo.class);

    /**
     * 普通的线程
     */
    public CompletableFuture<Void> normalCompletableFuture() {
        return CompletableFuture.runAsync(() -> {
            // 这里让线程休眠10秒
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                log.info("普通线程执行完毕");
            }
        });
    }

    /**
     * 存在异常的线程
     */
    public CompletableFuture<Void> exceptionCompletableFuture() {
        return CompletableFuture.runAsync(() -> {
            throw new RuntimeException("runAsync -> 发生了一个大的异常");
        });
    }

    /**
     * 存在异常的线程
     */
    public CompletableFuture<String> exceptionHasReturnCompletableFuture() {
        return CompletableFuture.supplyAsync(() -> {
            throw new RuntimeException("supplyAsync -> 发生了一个大的异常");
        });
    }

    public void testRunSupplyAsync() {
        CompletableFuture<Void> returnCompletableFuture = CompletableFuture.allOf(this.normalCompletableFuture(), this.exceptionHasReturnCompletableFuture());
        try {
            returnCompletableFuture.join();
        } catch (Throwable e) {
            Throwable throwable = Optional.ofNullable(e.getCause()).orElse(e);

            if (throwable instanceof RuntimeException rune) {
                throw rune;
            }

            throw new RuntimeException(throwable);
        }
    }

    public void testRunRunAsync() {
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(this.exceptionCompletableFuture(), this.normalCompletableFuture());
        try {
            voidCompletableFuture.join();
        } catch (Throwable e) {
            Throwable throwable = Optional.ofNullable(e.getCause()).orElse(e);

            if (throwable instanceof RuntimeException rune) {
                throw rune;
            }

            throw new RuntimeException(throwable);
        }
    }
}
